package com.onpositive.mediawiki.propertyparser;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.StringTokenizer;

import storage.v1.ParserV2;

import com.onpositive.data.units.DateWithAccuracy;
import com.onpositive.semantic.model.api.meta.IMeta;
import com.onpositive.semantic.model.api.property.IPropertyProvider;
import com.onpositive.units.AbstractPreprocessor;
import com.onpositive.units.AbstractValueParser;
import com.onpositive.units.ParsedDate;
import com.onpositive.units.ParsedValue;

public class DateParser extends AbstractValueParser {
	
//	static String[] months = {"january", "february", "mart","mart",
//							  "april","may","june","july","august",
//							  "september","october","november","december" };
//	static String[] seasons = {"winter","spring","summer","autumn"} ;
//	
	public DateParser(){
		super.id = ParsedDate.ID ;
	}

	@Override
	public ParsedValue parse(String s, IMeta meta,String comment) {
		
		String value = CompositeValueParser.killWikiRefsLeaveCaptions(s) ;
		value = ParserV2.killNoBreakSpace( value ) ;
		value = killParasiteWords( value ) ;
		value = value.toLowerCase() ;			
		value = value.replace(".",",");
		value = value.replace(" ",",");
		value = value.replaceAll(",+", ",") ;	
		
		StringTokenizer ts = new StringTokenizer(value, " ");
		String nextToken = ts.nextToken();
		
		ParsedDate result = produceDate(value,comment);
		if( result != null )
			return result ;
		
		String[] strArr = value.split(",") ;
		int l = strArr.length ;
		
		StringBuilder bld = new StringBuilder() ;
		for( int k = 2; k >= 0 ; k-- )
		{
			for( int i = 0 ; i < l-k ; i++ )
			{
				bld.delete(0, bld.length()) ;
				for( int j = 0 ; j < k+1 ; j++ )
				{
					bld.append( strArr[i+j]) ;
					bld.append(",") ;
				}
				value = bld.substring(0,bld.length()-1) ;
				result = produceDate(value,comment) ;
				if( result != null )
					return result ;
			}
		}
		return CompositeValueParser.getDefaultParser().parse(s,meta,comment) ;
	}

	public ParsedDate produceDate(String value, String comment) {
		try {
			DateFormat dateInstance = new SimpleDateFormat("dd,MM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("dd,MMMM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMM,dd,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("yyyy,MMMM", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		String value0 = value.replace(",", "") ;
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("ddMMMMyyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMMyyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}		
		
		if( value.contains(",") )
			return null ;
		try{
			DateFormat dateInstance = new SimpleDateFormat("yyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_YEAR, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		return null ;
	}
	
	private String killParasiteWords(String value) {
		
		String result = value ;

		result = result.replaceAll(" of ", " ") ;
		result = result.replaceAll(" on ", " ") ;		
		result = result.replaceAll("\\Aof\\s*", "") ;		
		result = result.replaceAll("\\Aon\\s*", "") ;
		result = result.replaceAll("(\\d)(th)", "$1") ;
		result = result.replaceAll("(\\d)(st)", "$1") ;
		result = result.replaceAll("\\A\\s*", "") ;

		return result ;
	}


	@Override
	public AbstractPreprocessor getPreprocessor() {
		return new AbstractPreprocessor() {
		@Override
			public String[] preprocess(String[] param, IPropertyProvider propertyProvider, IMeta meta ) {
				
				if (param == null || param.length < 2 || param[0] == null || param[1] == null)
					return null;
				
				boolean gotAChange = false ;
				
				String value = param[1].trim();				
				String value0 = resolveTemplates(value);
				
				if( !value.equals(value0) )
				{
					param[1] = value0 ;
					gotAChange = true ;
				}		
				
				return gotAChange ? param : null ; 
			}
	
			
	
			public String resolveTemplates(String str)
			{
				
				int l = str.length() ;
				StringBuilder builder = new StringBuilder() ;
				int prev = 0 ;								
				for( int i  = str.indexOf("{{") ; i >= 0 ; i = str.indexOf("{{", prev ) )
				{
					if( prev < i-1 ){
						builder.append( str.substring(prev,i).trim() ) ;
						if( i > 0 && Character.isWhitespace( str.charAt(i-1)) )
							builder.append( " " ) ;
					}
					i += 2 ;
					prev = str.indexOf("}}",i) ;
					prev = prev < 0 ? l-2 : prev ;
					
					String oldString = str.substring(i-2, prev+2);
					int ind = str.indexOf("|",i) ;
					ind = ind < 0 ? l : ind ;
					ind = Math.min( ind, prev ) ;
					
					@SuppressWarnings("unused")
					boolean test = i < 0 || ind < 0 || i > ind || ind > str.length() ;
					String templateName = str.substring(i,ind) ;
					resolveValue( templateName, str.substring(ind,prev), oldString, builder ) ;
					prev += 2 ;
				}
				builder.append( str.substring( prev, str.length() ) ) ;
				String result = builder.toString().trim() ;								
				return result;
			}
	
			private void resolveValue(String templateName, String str, String oldStr, StringBuilder builder )
			{
				ArrayList<String> arr = split(str);				
				
				if( templateName.equals("avyear") )
				{
					if( arr.size() != 0 ){
						builder.append( arr.get(0) ) ;
						builder.append( " " ) ;
						return ;
					}
				}
				builder.append( oldStr ) ;
				builder.append( " " ) ;
			}
	
			public ArrayList<String> split(String str) {
				ArrayList<String> arr = new ArrayList<String>() ;
				int prev = 0 ; 
				for( int i = str.indexOf("|") ; i >= 0 ; i = str.indexOf("|",prev) )
				{
					String s = str.substring(prev, i) ;
					if( s.length() != 0 )
						arr.add(s) ;
					
					prev = i+1 ;						
				}
				if( prev < str.length()-1 )
					arr.add(str.substring(prev)) ;
				return arr;
			}
		};
	}	

}
